#ifndef __LABOR_XMLDOC_BUILDER_H__
#define __LABOR_XMLDOC_BUILDER_H__
#include "../LaborCoreDef.h"
#include "LaborBaseLexer.h"
namespace XmlParser{
	class     xXmlDocument;
	class     xXmlNode;
	class     xXmlValue;


	enum 
	{
		UTF8_LEAD_0   = 0xefU,
		UTF8_LEAD_1   = 0xbbU,
		UTF8_LEAD_2   = 0xbfU,
		UTF16_LEAD_0 = 0xFF,
		UTF16_LEAD_1 = 0xFE
	};

	enum eStreamSeekDir
	{
		eSEEK_BEG,
		eSEEK_END,
		eSEEK_CUR,
	};

	class IStreamIO
	{
	public:
		virtual size_t read(char* buf,size_t len) = 0;
		virtual size_t write(const char* buf,size_t len) = 0;
		virtual size_t seek(long offs, eStreamSeekDir _dir) = 0;
		virtual size_t tell() = 0;
		virtual bool   close() = 0;
		virtual bool   eof() = 0;
		virtual bool   failed() = 0;
		virtual size_t length() = 0;
		virtual ~IStreamIO(){};
	public:
		template <typename T> size_t write(const T& data)
		{
			return write( (const char*) &data,sizeof(T));
		}

		template <typename T> size_t write(const T* data, size_t nObject)
		{
			return write( (const char*)data,sizeof(T)*nObject);
		}

		template <typename T> size_t read(T& data)
		{
			return read( (char*) &data,sizeof(T));
		}

		template <typename T> size_t read(T* data, size_t nObject)
		{
			return read( (char*)data,sizeof(T)*nObject);
		}

	};


	class  xMemStream : public IStreamIO
	{
	public:
		virtual size_t   read(char* buf,size_t len);
		virtual size_t   write(const char* buf,size_t len);
		virtual size_t   seek(long offs, eStreamSeekDir _dir);
		virtual size_t   tell();
		virtual bool     close();
		virtual bool     eof();
		virtual bool     failed(){ return m_Buffer == NULL || m_BufLen == 0 ; }
		virtual size_t   length(){ return m_BufLen ; }
	public:
		xMemStream(void* buf , int bufLen);
		xMemStream(const void* buf , int bufLen);
		xMemStream();
		virtual ~xMemStream(){};
	public:
		static xMemStream*  createInstance(const void* buf , int bufLen);
		static xMemStream*  createInstance(void* buf , int bufLen);
	public:

	protected:
		char* m_Buffer;
		int   m_BufLen;
		int   m_iPos;
		bool  m_bWriteable;
	};

	class  xDynaimcBufferStream : public xMemStream
	{
	public:
		virtual size_t          write(const char* buf,size_t len);
		virtual void            finish();
		virtual char*           getBuffer(){ return m_Buffer ; }
		virtual size_t          length(){ return m_iPos ; }
	public:
		xDynaimcBufferStream(int initLen = 1024);
		virtual ~xDynaimcBufferStream();
	};


	class xFileStream : public IStreamIO
	{
		FILE* m_fStream;
	public:	
		xFileStream(bool bWriteable = false);
		~xFileStream();
		size_t   read(char* buf, size_t byte_read);
		size_t   write(const char* buf,size_t len);
		size_t   seek(long _offset, eStreamSeekDir _dir);
		size_t   tell();
		bool     close();	
		bool     eof();
		bool     failed();
		size_t   length();
	public:
		static FILE*    xOpenFileRWB(const wchar_t* wcsFileName);
		static FILE*    xOpenFileRB(const wchar_t* wcsFileName);
	public:
		bool     open_stream(const wchar_t* _fileName);
		bool     open_stream(const wchar_t* _fileName ,bool bWriteable);
		bool     m_bWriteable;
		int      m_len;
	};

	//==============================================================
	//xCfg Lexer
	//==============================================================
	class  xXmlFileSource
	{
		bool           m_useMicrosoftBOM;
		wchar_t*       m_Buffer;
		wchar_t*       m_pData;
		bool           m_bNeedDelete;

		wchar_t*       loadUCS2FileBuffer(const char* ucs16Buff , int len, bool& bConverted);
	public :
		~xXmlFileSource();
		xXmlFileSource();
		bool            setSrc(const wchar_t* pTex);
		wchar_t*        getStr()   { return m_pData;   }
		bool            loadFile(const wchar_t* file);
		bool            loadMem(void* buf, int len);

	};

	class   xXmlLexer : public xBaseLexer<wchar_t, std::wstring>
	{
		int  __skipComment(const wchar_t* p);
	public:
		int  skipComment(const wchar_t* p);
		int  GetXMLStyleChar(const wchar_t* p, std::wstring& text );
		int  getString(const wchar_t* p      , std::wstring& text, const wchar_t* endTag , FUNC_IS_ACCEPT func);
		int  getString(	const wchar_t* p     , std::wstring& text , FUNC_IS_ACCEPT func);
	};

	class  xXmlBuilder
	{
	public:
		static bool loadFile(xXmlDocument* pDocument , const wchar_t* _file,bool bLoadHeader);
		static bool loadMem(xXmlDocument* pDocument , const wchar_t* _pSrc ,bool bLoadHeader);
		static bool loadMem(xXmlDocument* pDocument , void* _pSrc ,unsigned int iDataLen ,bool bLoadHeader);
	};

NAMESPACE_LABOR3D_END
#endif

